home *** CD-ROM | disk | FTP | other *** search
/ PC-Blue - MS DOS Public Domain Library / PC-Blue MS-DOS Public Domain Library - NYACC.iso / vol194 / kermasm.arc / MSFILE.ASM < prev    next >
Encoding:
Assembly Source File  |  1985-11-14  |  30.8 KB  |  1,104 lines

  1. ; Edit history:
  2.  
  3. ; [v2.28]
  4. ; Clear retry count before writing to it
  5. ; Redo unique filename generation.
  6. ; Jeff Damens 14 May 1985
  7.  
  8.     public    bufpnt, buff, fcb, cpfcb, chrcnt, fixfcb, init, init1,
  9.     public    gofil, outbuf, ptchr, gtchr, gtnfil, getfil, filbuf,
  10.     public    encode, decode, nulref, nulr, decbuf, errpack, rptq,
  11.     public    origr, rptct, rptval, clrfln, cxmsg, biterr, intmsg,
  12.     public    rtpos, erpos,rppos, stpos,nppos,rprpos,nrtpos,sppos,
  13.     public    kbpos,perpos,frpos, prtscr, prtfn
  14.     include msdefs.h
  15.  
  16. rptmin    equ    3        ; At least 3 of same char in a row.
  17.  
  18. ; equates for screen positioning
  19. scrfln    equ    0316H        ; Place for file name.
  20. scrkb    equ    0416H        ; Place for percent transferred.
  21. scrper    equ    0516H        ; Place for Kbytes transferred.
  22. scrst    equ    0616H        ; Place for status.
  23. scrnp    equ    0816H        ; Place for number of packets.
  24. scrnrt  equ    0916H        ; Place for number of retries.
  25. screrr  equ    0A16H        ; Place for error msgs. 
  26. scrhi    equ    0B16H        ; Err when 8th bit is on.
  27. scrfr    equ    0B16H        ; Rename file.
  28. scrint    equ    0B16H        ; Acknowledge interrupt. [20b]
  29. scrsp    equ    0C00H        ; Place for send packet.
  30. scrrp    equ    0E00H        ; Place for receive packet.
  31. scrrpr    equ    1100H        ; Prompt when Kermit ends.
  32.  
  33.  
  34.  
  35. datas    segment    public 'datas'
  36.     extrn    data:byte, flags:byte, trans:byte, pack:byte, hierr:byte
  37.     extrn    dosnum:byte
  38.  
  39. outlin  db    cr,lf,cr,lf
  40.         db      cr,lf,'           File name:'
  41.         db      cr,lf,'  KBytes transferred:'
  42.         db      cr,lf
  43.         db      cr,lf
  44.         db      cr,lf
  45.         db      cr,lf,'   Number of packets:'
  46.         db      cr,lf,'   Number of retries:'
  47.         db      cr,lf,'          Last error: None'
  48.         db      cr,lf,'        Last warning: None'
  49.         db      '$'
  50.  
  51. ermes4  db    '?Unable to make unique name$'
  52. erms10  db    '?Unable to receive data$'
  53. erms11  db    '?Disk full$'
  54. erms12    db    '?Unable to create file$'
  55. erms17  db    'Record length exceeds size of buffer$'
  56. infms5  db    'Renaming file to $'
  57. infms7    db    'File interrupt$'
  58. infms8    db    'File group interrupt$'
  59. hibit    db    'Warning - Non Ascii char$'
  60. crlf    db    cr,lf,'$'
  61. printer    db    0,'PRN        '
  62. spchar    db    24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH
  63.     db    3CH,3EH,7BH,7DH,5FH,5CH,5EH,7EH,7CH,60H
  64. spclen    equ    $-spchar    ; Number of special chars.
  65. spchar2    db    24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH
  66.     db    7BH,7DH,5FH,5EH,7EH,60H
  67. spc2len    equ    $-spchar2
  68. next    db    0FFH        ; No next character just yet.
  69. rptval    db    0        ; Repeated character.
  70. rptct    db    1        ; Number of times it's repeated.
  71. rptq    db    drpt        ; Repeat prefix.
  72. origr    db    drpt        ; Original repeat prefix.
  73. temp1    dw    ?        ; Temporary storage.
  74. temp2    dw    ?
  75. oloc    dw    0        ; Original buffer location. [21c]
  76. osiz    dw    0        ; Original buffer size. [21c]
  77. chrcnt  dw    ?        ; Number of chars in the file buffer.
  78. outpnt  dw    ?        ; Position in packet.
  79. bufpnt  dw    ?        ; Position in file buffer.
  80. fdtpnt    dw    ?        ; Pointer to within our file. 
  81. fcbptr  dw    ?        ; Position in FCB.
  82. cbfptr  dw    ?        ; Position in character buffer.
  83. filsiz    dw    0        ; Double word for filesize (in bytes.)
  84.     dw    0
  85. ofilsz    dw    0        ; Original file size percent adjusted (/100).
  86. tfilsz    dw    0        ; Bytes transferred.
  87.     dw    0
  88. oldper    dw    ?        ; old percentage
  89. oldkbt    dw    ?        ; old KB transferred.
  90. wrpmsg    db    ?        ; non-zero if we wrote percent message
  91. percnt    dw    100        ; Number to divide by for a percent.
  92. bufhex    dw    80H
  93. permsg    db    cr,' Percent transferred:$'
  94. cxzhlp    db    '¬X cancels file, ¬Z cancels batch'
  95.     db    ', ¬E aborts protocol'
  96.     db    ', ¬C quits'
  97.     db    ', Return retries'
  98.     db    '$'
  99. asmsg    db    ' AS '
  100. asmln    equ    $-asmsg
  101. filbuf  db    60H DUP(?)    ; Character buffer.
  102. buff    db    dmasiz DUP(?)    ; Use as our DTA.
  103. fcb    db    fcbsiz DUP(?)    ; Use as our FCB.
  104. cpfcb    db    fcbsiz DUP(?)    ; Save FCB in case of "*".   [7]
  105. decbuf    db    dmasiz DUP(?)    ; For decoding incoming data.
  106.  
  107. ; some data for unique filename generation
  108. fnbuf    db    100 dup (?)
  109. dotpos    dw    ?
  110. fnlen    db    ?
  111. unum    dw    ?
  112.  
  113. datas    ends
  114.  
  115. code    segment    public
  116.     extrn    spack:near, cmblnk:near, locate:near, nout:near
  117.     extrn    putmod:near, poscur:near, clearl:near, fcbcpy:near
  118.     extrn    isfile:near
  119.     assume  cs:code,ds:datas
  120.  
  121. ; Position cursor for an error message.
  122.  
  123. ERPOS    PROC     NEAR
  124.     cmp flags.xflg,1    ; Packet header seen? [21c start] 
  125.     jne erp0        ; No, do as normal. 
  126.     mov dx,offset crlf
  127.     mov ah,prstr
  128.     int dos
  129.     ret
  130. erp0:    mov dx,screrr
  131.     jmp poscur
  132. ERPOS    ENDP
  133.  
  134. ; Position cursor for number of retries message.
  135.  
  136. RTPOS    PROC     NEAR
  137.     cmp flags.xflg,1    ; Packet header seen? [21c]
  138.     jne rtp0        ; No, do as normal.
  139.     ret
  140. rtp0:    mov dx,scrnrt
  141.     call poscur
  142.     jmp clearl
  143. RTPOS    ENDP
  144.  
  145. ; Reassure user that we acknowledge his ¬X/¬Z.
  146.  
  147. INTMSG    PROC    NEAR
  148.     cmp flags.xflg,0    ; Writing to screen?
  149.     jne int1        ; Yes. Don't do anything.
  150.     mov dx,scrint
  151.     call poscur
  152.     call clearl
  153.     mov dx,offset infms7    ; File interrupted?
  154.     cmp flags.cxzflg,'X'    ; Yes. 
  155.     je int0
  156.     mov dx,offset infms8    ; File group interrupted.
  157. int0:   mov ah,prstr
  158.         int dos
  159. int1:    ret
  160. INTMSG    ENDP
  161.  
  162. ; Print err message that found a non-standard-Ascii char in the file.
  163.  
  164. BITERR    PROC    NEAR
  165.     cmp flags.remflg,0    ; remote mode?
  166.     jne biter1        ; yes, no printing.
  167.     push bx
  168.     mov dx,scrhi
  169.     call poscur
  170.     call clearl
  171.     mov ah,prstr
  172.     mov dx,offset hibit
  173.     int dos
  174.     pop bx
  175. biter1:    ret
  176. BITERR    ENDP        
  177.  
  178. ;  Clear out message about interrupted file.
  179.  
  180. CXMSG    PROC    NEAR
  181.     cmp flags.xflg,0    ; Writing to screen?
  182.     jne cxm0        ; Yes. Don't do anything.
  183.     mov dx,scrint
  184.     call poscur
  185.     call clearl
  186. cxm0:    ret
  187. CXMSG    ENDP
  188.  
  189. ;  Clear out the old filename on the screen. 
  190.  
  191. CLRFLN    PROC    NEAR
  192.     mov dx,scrfln
  193.     call poscur
  194.     call clearl        ; Clear to end of line. [19a]
  195.     ret
  196. CLRFLN    ENDP
  197.  
  198. ; some random screen positioning functions
  199. kbpos:    mov dx,scrkb        ; KBytes transferred.
  200.     call poscur
  201.     jmp clearl
  202. perpos:    mov dx,scrper        ; Percent transferred.
  203.     call poscur
  204.     jmp clearl
  205. frpos:    mov dx,scrfr        ; Say renamed file.
  206.     call poscur
  207.     jmp clearl
  208. stpos:    mov dx,scrst        ; Print status of file transfer.
  209.     call poscur
  210.     jmp clearl
  211. nppos:    mov dx,scrnp        ; Number of packets sent.
  212.     jmp poscur
  213. rprpos:    mov dx,scrrpr        ; Reprompt position.
  214.     jmp poscur
  215. nrtpos:    mov dx,scrnrt        ; Number of retries.
  216.     call poscur
  217.     jmp clearl
  218. sppos:    mov dx,scrsp        ; Send packet location.
  219.     jmp poscur
  220. rppos:    mov dx,scrrp        ; Receive packet location.
  221.     jmp poscur
  222.  
  223.  
  224.  
  225. ;    Initialize buffers and clear line.
  226.  
  227. INIT    PROC    NEAR
  228.     call cmblnk
  229.     call locate
  230.     mov ah,prstr        ; Put statistics headers on the screen.
  231.     mov dx,offset outlin
  232.     int dos
  233.     mov dx,offset cxzhlp
  234.     call putmod        ; write mode line
  235.     mov wrpmsg,0        ; haven't printed the messsage yet.
  236.     call init1
  237.     ret
  238. INIT    ENDP
  239.  
  240. INIT1    PROC    NEAR
  241.     mov chrcnt,dmasiz           ; Number of chars left.
  242.     mov bufpnt,offset buff           ; Addr for beginning.
  243.     mov hierr,0
  244.     ret
  245. INIT1    ENDP
  246.  
  247. ;    Output the chars in a packet.
  248.  
  249. ; Called with AX = size of the data, BX = address of source.
  250.  
  251. FILEIO    PROC    NEAR     
  252. ptchr:  mov cx,ax
  253.     mov ax,offset outbuf    ;Where to put data when buffer gets full.
  254.     jmp decode
  255.  
  256. ; CX = Size of data, BX = Address of data, AX = Routine to call to
  257. ; dump data.
  258.  
  259. decode: push si
  260.     push di
  261.     push es
  262.     push dx
  263.     push ax
  264.     mov ax,ds
  265.     mov es,ax
  266.     pop ax
  267.     mov si,bx        ; Source of data.
  268.     mov bx,ax        ; Coroutine to call.
  269.     mov di,bufpnt        ; Destination of data.
  270.     mov dh,0        ; assume no quote char
  271.     cmp trans.ebquot,'N'    ; no quoting?
  272.     je decod1        ; yes, keep going
  273.     cmp trans.ebquot,'Y'    ; or not doing it?
  274.     je decod1        ; yes, keep going
  275.     mov dh,trans.ebquot    ; otherwise use quote char
  276.  
  277. decod1:    mov rptct,0        ; Reset.
  278.     mov rptval,0        ; Ditto.
  279.     dec cx
  280.     jge dcod11        ; More data.
  281.     jmp decod6        ; Else, we're through.
  282. dcod11:    dec chrcnt        ; Decrement number of chars in dta.
  283.     jns decod2        ; Continue if space left.
  284.     push cx
  285.     push dx
  286.     push bx
  287.     call bx            ; Output it if full.
  288.      jmp decod5        ;  Error return if disk is full.
  289.      nop
  290.     pop bx
  291.     pop dx
  292.     pop cx
  293.     mov di,bufpnt
  294. decod2:    cmp rptct,0        ; Doing a repeat?
  295.     je dcod20        ; No, so go get a character.
  296.     mov ah,0
  297.     mov al,rptval        ; Get the character we're repeating.
  298.     jmp decod4        ; And write it out to the file.
  299. dcod20:    lodsb            ; Pick up a char.
  300.     cmp rptq,0        ; Doing repeat quoting?
  301.     je dcod21        ; Nope, skip this part.
  302.     cmp al,rptq        ; Did we pick up the repeat quote char?    
  303.     jne dcod21        ; No, continue processing it.
  304.     lodsb            ; Get the size.
  305.     dec cx            ; Modify buffer count.
  306.     sub al,20H        ; Was made printable.
  307.     mov rptct,al        ; Remember how many repetitions.
  308.     lodsb            ; Get the char to repeat.
  309.     dec cx            ; Modify buffer count.
  310. dcod21:    mov ah,00H        ; Assume no 8-bit quote char. [21b start]
  311.     cmp al,dh        ; This the 8-bit quot char?
  312.     jne decod3
  313.     lodsb            ; Get the real character.
  314.     dec cx            ; Decrement # chars in packet
  315.     mov ah,80H        ; Turn on 8-bit quot char flag. [21b end] 
  316. decod3: cmp al,trans.squote    ; Is it the quote char? [21b] [21c]
  317.     jne decod4        ; If not proceed.
  318.     lodsb            ; Get the quoted character
  319.     dec cx            ; Decrement # of chars in packet.
  320.     or ah,al        ; save parity (combine with prefix)
  321.     and ah,80h        ; only parity
  322.     and al,7FH        ; Turn off the parity bit.
  323.     cmp al,trans.squote    ; Is it the quote char? [21c]
  324.     je decod4        ; If so just go write it out.
  325.     cmp al,dh        ; This the 8-bit quot char?
  326.     je  decod4        ; If so, just go write it out
  327.     cmp al,rptq        ; Is is the repeat quote character?
  328.     je decod4        ; If so, just write it out.
  329.     add al,40H        ; Make it a control char again.
  330.     and al,7FH        ; Modulo 128.
  331. decod4: or al,ah        ; or in parity
  332.     stosb            ; store the character
  333.     dec rptct        ; Repeat counter.
  334.     cmp rptct,0        ; Write out char again?
  335.     jg dcod41
  336.     jmp decod1        ; No, get next char.
  337. dcod41:    mov rptval,al        ; Save the char.
  338.     jmp dcod11        ; and loop to next char.
  339. decod5:    pop bx
  340.     pop dx            ; dx is pushed twice (really)
  341.     pop cx
  342.     pop dx
  343.     pop es
  344.     pop di
  345.     pop si
  346.     ret
  347. decod6:    mov bufpnt,di
  348.     pop dx
  349.     pop es
  350.     pop di
  351.     pop si
  352.     jmp rskp        ; Return successfully if done.
  353.  
  354.  
  355.  
  356.     ; output the buffer, reset bufpnt and chrcnt
  357.  
  358. outbuf: cmp flags.xflg,1    ; Writing to screen? [21c] 
  359.     je outbf2        ; Yes, handle specially. [21c] 
  360.     push bx
  361.     mov ah,writef        ; The write code.
  362.     mov dx,offset fcb
  363.     int dos            ; Write the record.
  364.     pop bx
  365.     cmp al,0        ; Successful.
  366.     jz outbf1
  367.     push ax            ; Remember the return code. [20d]
  368.     call abfil        ; Fix things up before aborting. [20d]
  369.     pop ax            ; Retrive return code. [20d]
  370.     cmp al,01
  371.     jz outbf0
  372.     call erpos
  373.     mov ah,prstr
  374.     mov dx,offset erms17    ; Record length exceeds dta.
  375.     int dos
  376.     ret
  377. outbf0: call erpos
  378.     mov ah,prstr        ; Tell about it.
  379.     mov dx,offset erms11    ; Disk full error.
  380.     int dos
  381.     ret
  382. outbf1:    add tfilsz+2,80H    ; Say 128 more characters received.
  383.     adc tfilsz,0
  384.     call kbpr        ; Print the kilobytes received.
  385.     call perpr        ; Print the percent ('?' for now).
  386. outb11:    mov bufpnt,offset buff    ; Addr for beginning.
  387.     mov chrcnt,dmasiz-1    ; Buffer size.
  388.     jmp rskp
  389. outbf2:    mov cx,dmasiz-1        ; Number of chars to write. [21c]
  390.     sub cx,chrcnt        ; minus # of unused in buffer
  391.     jle outb11        ; none to print, don't try
  392.     mov di,offset buff    ; Where they are. [21c]
  393.     call prtscr        ; Output buffer to screen. [21c]
  394.     jmp outb11        ; Reset counter & pointer. [21c]
  395.  
  396. ;  Tidy up before aborting.    [20d]
  397. ABFIL    PROC    NEAR
  398.     mov flags.xflg,1    ; Writing to screen?
  399.     je abfil0        ; Yes don't delete "file".
  400.     mov ah,closf        ; Close the file.
  401.     mov dx,offset fcb
  402.     int dos
  403.     cmp flags.abfflg,1    ; Delete what got across or keep it?
  404.     jne abfil0        ; Nope, keep it.
  405.     mov ah,delf        ; Delete it.
  406.     mov dx,offset fcb
  407.     int dos
  408. abfil0:    mov bx,offset erms10    ; Text of message to send.
  409.     call errpack        ; Send an error packet.
  410.     ret
  411. ABFIL    ENDP
  412.  
  413. ; General routine for sending an error packet.  Register BX should
  414. ; point to the text of the message being sent in the packet. [20f]
  415.  
  416. ERRPACK    PROC    NEAR
  417.     mov di,offset data    ; Where to put the message.
  418.     mov al,0
  419. errp1:    mov ah,[bx]
  420.     cmp ah,'$'        ; At end of message?
  421.     je errp2
  422.     inc al            ; Remember number of chars in msg.
  423.     mov [di],ah
  424.     inc bx
  425.     inc di
  426.     jmp errp1
  427. errp2:    mov ah,0
  428.     mov pack.argbk1,ax
  429.     mov ah,'E'        ; And send an error packet.
  430.     call spack
  431.      ret            ; Return if succeed or fail.
  432.     nop
  433.     nop
  434.     ret
  435. ERRPACK    ENDP
  436.  
  437. ;    Get the chars from the file.
  438.  
  439. gtchr:  cmp flags.filflg,0    ; Is there anything in the DMA?
  440.     jz gtchr0        ; Yup, proceed.
  441.     mov ah,rptq
  442.     mov origr,ah        ; Save repeat prefix here.
  443.     mov rptct,1        ; Number of times char is repeated.
  444.     mov rptval,0        ; Value of repeated char.
  445.     call inbuf
  446.      jmp gtchr1        ; No more chars, go return EOF.
  447.      nop            ; Make three bytes long.
  448. gtchr0:    mov bx,offset inbuf
  449.     jmp encode
  450. gtchr1:    mov ax,0ffffh
  451.     ret
  452.  
  453. ; encode - writes data portion of kermit packet into filbuf.
  454. ; expects BX to contain the address of a routine to refill the buffer,
  455. ; chrcnt to be the # of chars in the buffer, trans.maxdat to contain
  456. ; the maximum size of the data packet, bufpnt to contain a pointer to
  457. ; the source of the characters.
  458. ; Returns: AX/ the number of characters actually written to the buffer.
  459.  
  460. encode:    mov cl,trans.maxdat    ; Maximum packet size. [21b]
  461.     mov ch,0
  462.     mov di,offset filbuf    ; Where to put the data.
  463.     mov si,bufpnt        ; pointer into source buffer
  464.     mov dl,trans.rquote    ; send quote char
  465.     mov dh,0        ; assume no 8-bit quoting
  466.     cmp trans.ebquot,'N'    ; not doing 8-bit quoting
  467.     je encod1
  468.     cmp trans.ebquot,'Y'    ; or can but won't?
  469.     je encod1
  470.     mov dh,0ffh        ; remember we have to do it
  471. encod1: dec cx            ; Decrement output buffer counter.
  472.     jge encod2        ; Go on if there is more than one left.
  473.     sub di,offset filbuf
  474.     mov ax,di
  475.     mov bufpnt,si        ; update pointer into DMA.
  476.     jmp rskp
  477. encod2: cmp chrcnt,0        ; Any data in buffer?
  478.     jg encod3        ; yes, skip over buffer refill.
  479.     call bx            ; Get another buffer full.
  480.      jmp encod8
  481.     mov si,bufpnt        ; update position in DMA.
  482.     cmp chrcnt,0         ; no characters returned?
  483.     jne encod3        ; Got some, keep going.
  484.     jmp encod8        ; none, assume eof.
  485. encod3: dec chrcnt        ; Decrement input count.
  486.     lodsb
  487.         cmp flags.eofcz,0       ; Is a control-z an end of file? [27b]
  488.         je encd30               ; No, don't have to look for one. [27b]
  489.         cmp al,'Z'-40H          ; Is this a control-Z? [27b]
  490.         jne encd30              ; No, skip eof-processing. [27b]
  491.         mov flags.eoflag,0FFH   ; Yes, set eof flag. [27b]
  492.     mov flags.filflg,0FFH    ; No more input in buffer. [28]
  493.     mov chrcnt,0        ; Ditto. [28]
  494.         jmp encod8              ; Go set character count and return. [27b]
  495. encd30: cmp rptq,0        ; Are we doing repeat prefixing? 
  496.     je encd3x        ; Nope, skip next part.
  497.     cmp chrcnt,0        ; Are we on the last character?
  498.     jle encd31        ; Yes, so there's no next character.
  499.     cmp rptct,94        ; Max number that we can put in a byte.
  500.     je encd31        ; Then that's it.
  501.     mov ah,[si]        ; Get the next character.
  502.     cmp al,ah        ; Is current char == next char?
  503.     jne encd31
  504.     inc rptct        ; Number of times char appears.
  505.     mov rptval,al        ; Remember the character.
  506.     inc cx            ; Repeats don't take up so much buffer space.
  507.     jmp encod1        ; Keep checking for more.
  508. encd31:    cmp rptct,1        ; Were previous characters repeats?
  509.     je encd3x        ; No, so just add this char.
  510.     cmp rptct,rptmin    ; Are we within bounds for repeat prefixing?
  511.     jge encd32        ; Yes, use repeat prefixing.
  512.     mov al,rptct
  513.     mov ah,0
  514.     sub si,ax        ; Not enough characters to warrant it.
  515.     mov rptval,0        ; Clear out this value.
  516.     inc cx            ; Adjust output buffer pointer.
  517.     mov al,rptq
  518.     mov origr,al        ; Save original repeat prefix.
  519.     mov rptq,0        ; Pretend we're not doing the prefixing.
  520.     mov al,rptct
  521.     mov ah,0
  522.     add chrcnt,ax        ; Adjust input buffer pointer.
  523.     jmp encod1        ; Reprocess those characters.
  524. encd32:    push ax            ; Do repeat prefixing - save data.
  525.     mov al,rptq        ; Add repeat prefix char.
  526.     stosb
  527.     dec cx            ; Account for it in buffer size.
  528.     mov al,rptct        ; Get the repeat count.
  529.     add al,20H        ; Make it printable.
  530.     stosb            ; Add to buffer.
  531.     dec cx
  532.     pop ax            ; Get back the actual character.
  533.     mov rptct,1        ; Reset repeat count.
  534.     mov rptval,0        ; And this.
  535. encd3x:    cmp dh,0        ; are we doing 8-bit quoting?
  536.     je encod4        ; no, forget this.
  537.     test al,80h        ; parity on?
  538.     je encod4        ; no, don't bother with this
  539.     and al,7fh        ; turn off parity
  540.     push ax            ; save original char for a bit
  541.     dec cx            ; decrement # of chars left
  542.     mov al,trans.ebquot    ; get quote char
  543.     stosb            ; save in buffer
  544.     pop ax            ; restore character
  545. encod4:    mov ah,al        ; save character
  546.     and ah,80h        ; only parity
  547.     and al,7fh        ; turn off parity in character
  548.     cmp al,' '        ; Compare to a space.
  549.     jl encod5        ; If less then its a control char.
  550.     cmp al,del        ; Is the char a delete?
  551.     jz encod5        ; Go quote it.
  552.     cmp al,dl        ; Is it the quote char?
  553.     je encod6        ; Yes - go add it. [21b start]
  554.     cmp dh,0        ; are we doing 8-bit quoting?
  555.     je encd41        ; no, don't translate it
  556.     cmp al,trans.ebquot    ; Is it the 8-bit quote char?
  557.     je encod6        ; Yes, just output with quote
  558. encd41:    cmp origr,0        ; Doing repeat prefixing?
  559.     je encod7        ; No, don't check for quote char.
  560.     cmp al,origr        ; Is this the repeat quote character.
  561.     je encod6        ; Yes, then quote it.
  562.     jmp short encod7    ; else don't quote it.
  563. encod5:    add al,40h        ; control char, uncontrollify
  564.     and al,7fh
  565. encod6:    push ax            ; save the char
  566.     dec cx
  567.     mov al,dl
  568.     stosb
  569.     pop ax
  570. encod7:    or al,ah        ; put parity back
  571.     stosb
  572.     cmp rptct,1        ; One occurence of this char?
  573.     jne encd7x
  574.     mov al,origr
  575.     mov rptq,al        ; Restore repeat quote char.
  576.     jmp encod1        ; Yes, so loop around for some more.
  577. encd7x:    dec rptct        ; Add another entry of this char.
  578.     jmp encod1        ; With quoting and all.
  579.  
  580. encod8: sub di,offset filbuf
  581.     or di,di
  582.     je encod9        ; Nope.
  583.     mov ax,di
  584.     jmp rskp
  585. encod9: mov ax,0FFFFH        ; Get a minus one.
  586.     ret
  587.  
  588.  
  589. inbuf:  mov ah,flags.eoflag    ; Have we reached the end?
  590.     cmp ah,0
  591.     jz inbuf0
  592.     ret            ; Return if set.
  593. inbuf0:    push si
  594.     push di
  595.     push dx
  596.     push bx            
  597.     push cx
  598.     mov bx,offset buff    ; Set the r/w buffer pointer.
  599.     mov bufpnt,bx
  600.     mov ah,readf        ; Read a record.
  601.     mov dx,offset fcb
  602.     int dos
  603.     mov cx,filsiz
  604.     cmp cx,0        ; Check for 128 chars or less left.
  605.     jne inbuf1        ; Still have data left.
  606.     mov ax,ds
  607.     mov es,ax
  608.     mov si,offset filsiz+2
  609.     mov di,offset bufhex
  610.     cmps filsiz+2,es:bufhex
  611.     ja inbuf1        ; More than 128 chars.
  612.     mov flags.eoflag,0FFH    ; Set End-of-file.
  613.     mov cx,filsiz+2
  614.     mov chrcnt,cx        ; Return proper number of chars.
  615.     mov flags.filflg,0    ; Buffer not empty.
  616.     pop cx
  617.     pop bx
  618.     pop dx
  619.     pop di
  620.     pop si
  621.     jmp rskp
  622. inbuf1:    sub filsiz+2,80H    ; Sent another 128 chars.
  623.     sbb filsiz,0        ; Account for the doubleword.
  624.     add tfilsz+2,80H    ; Book keeping for the same.
  625.     adc tfilsz,0
  626.     push ax
  627.     call kbpr        ; Print the kilobytes sent.
  628.     call perpr        ; Print the percent sent.
  629.     pop ax
  630.     mov al,80H        ; Use as counter for number of chars read.
  631.     pop cx
  632.     pop bx
  633.     pop dx
  634.     pop di
  635.     pop si
  636.     mov ah,0        ; Zero the flag (buffer not empty).
  637.     mov chrcnt,ax        ; Number of chars read from file.
  638.     mov flags.filflg,0    ; Buffer not empty.
  639.     jmp rskp
  640.  
  641. nulref:    mov chrcnt,0        ; No data to return.
  642.     jmp rskp
  643.  
  644. nulr:    ret
  645.  
  646. ; Print the number of Kilobytes transferred.
  647.  
  648. kbpr:    cmp flags.remflg,0    ; remote mode?
  649.     jne kbpr1        ; yes, no printing.
  650.     mov ax,tfilsz+2
  651.     mov bx,tfilsz
  652.     mov cl,10
  653.     shr ax,cl        ; divide by 1024
  654.     mov cl,6        ; high order moves 16-10 = 6 bits
  655.     shl bx,cl
  656.     or ax,bx
  657.     cmp ax,oldkbt        ; is it the same?
  658.     je kbpr1        ; yes, skip printing
  659.     mov oldkbt,ax        ; save new # of kb
  660.     push ax
  661.     call kbpos        ; Postion the cursor.
  662.     pop ax
  663.     call nout        ; Print the number of KBytes transferred.
  664. kbpr1:    ret
  665.  
  666. ; Print the percent transferred.
  667.  
  668. perpr:    cmp flags.remflg,0    ; remote mode?
  669.     jne perpr5        ; yes, no printing.
  670.     mov ax,tfilsz
  671.     or ax,tfilsz+2
  672.     cmp ax,oldper        ; same as it was before?
  673.     je perpr5        ; yes, don't bother printing.
  674.     mov oldper,ax        ; remember this for next time
  675.     cmp ofilsz,0        ; No divide by zeroes.
  676.     je perpr5        ; If not proceed.
  677.     cmp wrpmsg,0        ; did we write the percentage message?
  678.     jne perpr1        ; yes, skip this part
  679.     call perpos        ; position cursor
  680.     mov dx,offset permsg
  681.     mov ah,prstr
  682.     int dos            ; write out message
  683.     mov wrpmsg,1        ; init flag so we don't do it again
  684. perpr1:    call perpos        ; Position the cursor.
  685. perpr2:    mov dx,tfilsz        ; Get the high order word.
  686.     mov ax,tfilsz+2        ; Get the low order word.
  687.     div ofilsz        ; Div by percent adjusted original file size.
  688.     cmp ax,100        ; > 100% ?
  689.     jle perpr3        ; no, accept it
  690.     mov ax,100        ; else just use 100
  691. perpr3:    call nout
  692.     mov dl,'%'        ; Load a percent sign.
  693. perpr4:    mov ah,conout        ; Print the character.
  694.     int dos
  695. perpr5:    ret
  696.  
  697. getfil: mov ah,0FFH
  698.     mov flags.filflg,ah    ; Nothing in the DMA.
  699.     mov ax,0
  700.     mov flags.eoflag,ah    ; Not the end of file.
  701.     mov bx,offset fcb+0CH
  702.     mov [bx],ax        ; Zero the current block number.
  703.     mov bx,offset fcb+0EH
  704.     mov [bx],ax        ; Ditto for Lrecl.
  705.     mov bx,offset fcb+20H
  706.     mov [bx],ah        ; Zero the current record (of block).
  707.     inc bx
  708.     mov [bx],ax        ; Same for record (of file). 
  709.     mov bx,offset fcb+23H
  710.     mov [bx],ax
  711.     mov ah,openf        ; Open the file.
  712.     mov dx,offset fcb
  713.     int dos
  714.     mov dx,word ptr fcb+18    ; get file size (hi order word)
  715.     mov filsiz,dx
  716.     mov ax,word ptr fcb+16    ; lo order word
  717.     mov filsiz+2,ax
  718.     div percnt        ; Divide by 100.
  719.     mov ofilsz,ax
  720.     mov tfilsz,0        ; Set bytes sent to zero.
  721.     mov tfilsz+2,0
  722.     mov oldkbt,-1
  723.     mov oldper,-1
  724.     cmp filsiz,0        ; Null file?
  725.     jne getfl0        ; Nope.
  726.     cmp filsiz+2,0        ; Null file?
  727.     jne getfl0        ; Nope.
  728.     mov flags.eoflag,0FFH    ; Set EOF.
  729. getfl0:    jmp rskp
  730.  
  731.  
  732. gtnfil: cmp flags.cxzflg,'Z'    ; Did we have a ¬Z? [20b]
  733.     je gtn5            ; If yes, we're done sending files. [20b]
  734.     cmp flags.wldflg,0    ; Was there a "*"?        [7 start]
  735.     je gtn5            ; Nope.
  736.     mov bx,offset cpfcb    ; Get FCB from last check for file.  
  737.     mov di,offset fcb    ; Copy to FCB.
  738.     mov cl,37        ; Size of FCB.
  739.     call fcbcpy
  740. gtn2:    mov ah,snext
  741.     mov dx,offset fcb    ; More files?
  742.     int dos
  743.     cmp al,0FFH
  744.     je gtn5
  745.     mov bx,offset fcb
  746.     mov di,offset cpfcb
  747.     mov cl,37
  748.     call fcbcpy        ; Copy from FCB.
  749.     mov di,offset fcb+1    ; Get name of next file to send.
  750.     mov bx,offset buff+1
  751.     mov cl,11
  752.     call fcbcpy
  753.     call getfil        ; Initialize
  754.      jmp r
  755.     jmp rskp            
  756. gtn5:    mov flags.wldflg,0    ; Reset wild card flag.
  757.     ret                         ;  [7 end]
  758.  
  759.  
  760. ; Get the file name from the data portion of the F packet.
  761. ; prints the filename, handles any manipulation of the filename
  762. ; necessary, including changing the name to prevent collisions.
  763. ; Fills in the (global) fcb called fcb.  Deletes the file
  764. ; and creates a new one.
  765.  
  766. gofil:  cmp flags.xflg,1    ; Remote command?
  767.     jne gofil1        ; No....
  768.     jmp gofi20        ; Yes so skip this stuff.
  769. gofil1:    cmp flags.nmoflg,1    ; Overriding name from other side?
  770.     jne gofil4        ; No - get the filename.
  771. ; this bogusity copies the filename from the fcb into the data
  772. ; area so the rest of the filename processing will be symmetric...
  773.  
  774.     mov si,offset fcb+1
  775.     mov di,offset data
  776.     mov cx,9        ; # of chars in first part
  777.     mov bl,0        ; haven't gone thru this yet...
  778. gofil2:    lodsb            ; get a byte
  779.     cmp al,' '        ; space?
  780.     je gofil3        ; yes, break loop
  781.     stosb
  782.     loop gofil2
  783. gofil3:    cmp bl,0
  784.     jne gofil4        ; been thru here already, exit
  785.     mov bl,1
  786.     mov al,'.'
  787.     stosb            ; this is where the dot goes
  788.     mov cx,3        ; # of chars in extension
  789.     mov si,offset fcb+9    ; this is where the extension starts
  790.     jmp gofil2        ; loop thru again
  791.  
  792. gofil4:    mov al,0
  793.     stosb            ; tie off the filename
  794.     cmp flags.destflg,0    ; writing to printer?
  795.     jne gofil5        ; no, go on
  796.     mov ax,offset printer    ; this is filename now
  797.     jmp gofi16        ; rejoin code later...
  798.  
  799. gofil5:    mov si,offset data    ; this is file name
  800.     mov ah,0        ; no dot seen yet
  801. gofil6:    lodsb            ; get a byte of name
  802.     cmp al,0        ; end of name
  803.     je gofil8
  804.     cmp al,'.'        ; dot?
  805.     jne gofil7        ; no, go on
  806.     cmp ah,0        ; seen one yet?
  807.     jne gofil8        ; yes, this is the end
  808.     mov ah,1        ; remember we've seen it
  809.     jmp gofil6        ; and don't verify it
  810. gofil7:    call verlet
  811.     mov [si-1],al        ; update name
  812.     jmp gofil6        ; loop thru rest of name
  813. gofil8:    mov al,0        ; null for end
  814.     mov [si-1],al        ; make sure it's terminated
  815.  
  816. ; filename is now in data area, all converted
  817. gofil9:    cmp flags.remflg,0    ; remote mode?
  818.     jne gofi10        ; yes, don't print it.
  819.     call prtfn        ; Print the file name.
  820. gofi10:    mov ax,offset data    ; point to name
  821.     cmp flags.flwflg,0    ; Is file warning on?
  822.     je gofi16        ; no, just proceed
  823.     call isfile        ; does it exist?
  824.     mov ax,offset data    ; reload ptr in case...
  825.     jc gofi16        ; no, just proceed
  826.     call unique        ; generate unique name
  827.     cmp ax,0        ; couldn't do it?
  828.     je gofi14        ; no, go complain
  829.     push ax            ; save unique name
  830.     cmp flags.remflg,0    ; remote mode?
  831.     jne gofi13        ; yes, skip printing
  832.     push ax            ; save unique name again
  833.     call frpos        ; Position cursor. 
  834.     mov ah,prstr        ; Inform the user we are renaming the file.
  835.     mov dx,offset infms5
  836.     int dos
  837. gofi11:    pop si            ; get name back again
  838. gofi12:    lodsb
  839.     cmp al,0
  840.     jz gofi13
  841.     mov dl,al
  842.     mov ah,conout
  843.     int dos            ; print the filename
  844.     jmp gofi12
  845. gofi13:    pop ax            ; restore name
  846.     jmp gofi16        ; and go handle file
  847.  
  848. gofi14:    cmp flags.remflg,0    ; remote mode?
  849.     jne gofi15        ; yes, no printing
  850.     call erpos        ; Position cursor.
  851.     mov ah,prstr        ; Tell the user that we can't rename it.
  852.     mov dx,offset ermes4
  853.     int dos
  854. gofi15:    mov bx,dx        ; Tell host can't rename.  [20f]
  855.     call errpack        ; Send error packet before abort. [20f]
  856.     ret
  857.  
  858. gofi16:    mov di,offset fcb    ; place to put it
  859.     mov si,ax        ; pointer to name
  860.     cmp flags.droflg,0    ; overriding default drive?
  861.     jne gofi17        ; no, keep going
  862.     mov fcb,0        ; else use default drive
  863. gofi17:    mov al,2        ; don't change drive in fcb
  864.     mov ah,prsfcb
  865.     int dos            ; parse it
  866.     mov ah,delf        ; Delete the file if it exists.
  867.     mov dx,offset fcb
  868.     int dos
  869.     mov flags.nmoflg,0
  870.     mov flags.droflg,0    ; reset flags (!)
  871.  
  872.     mov ax,0
  873.     mov word ptr fcb+0CH,ax
  874.     mov word ptr fcb+0EH,ax    ; zero current block and lrecl
  875.     mov fcb+20H,al
  876.     mov word ptr fcb+21h,ax    ; zero record within file
  877.     mov word ptr fcb+23H,ax    ; file size unknown
  878.     mov ofilsz,0        ; File size unknown.
  879.     mov tfilsz,0        ; Set bytes received to zero.
  880.     mov tfilsz+2,0
  881.     mov oldkbt,-1
  882.     mov oldper,-1
  883.     mov ah,makef        ; Now create it.
  884.     mov dx,offset fcb
  885.     int dos
  886.     cmp al,0FFH        ; Is the disk full?
  887.     je gofi18
  888.     jmp rskp
  889. gofi18:    cmp flags.remflg,0    ; remote mode?
  890.     jne gofi19        ; yes, don't try printing
  891.     call erpos        ; Position cursor.
  892.     mov ah,prstr        ; If so tell the user.
  893.     mov dx,offset erms12
  894.     int dos
  895.     mov bx,dx
  896. gofi19:    call errpack        ; Send an error packet.
  897.     ret
  898. gofi20:  cmp pack.argbk1,0    ; Any data in "X" packet? [21c start]
  899.     je gofi21        ; Nothing to print. 
  900.     mov ah,prstr
  901.     mov dx,offset crlf
  902.     int dos    
  903.     int dos            ; Print another crlf.
  904.     mov di,offset data    ; Where data is.
  905.     mov cx,pack.argbk1    ; How much data we have.
  906.     call prtscr        ; Print it on the screen.
  907. gofi21:    mov ah,prstr
  908.     mov dx,offset crlf
  909.     int dos
  910.     jmp rskp        ; And done. [21c end]
  911.  
  912.  
  913. FILEIO    ENDP
  914.  
  915. ; Passed char of incoming filename in AL.  Verify that it is legal
  916. ; and if not change it to an "X".
  917. verlet:    cmp al,'0'
  918.     jb ver2            ; See if it's a legal weird char.
  919.     cmp al,'z'
  920.     ja ver2
  921.     cmp al,'9'
  922.     jbe ver1        ; It's between 0-9 so it's OK.
  923.     cmp al,'A'
  924.     jb ver2            ; Coud be a weird char.
  925.     cmp al,'Z'
  926.     jbe ver1        ; It's A-Z so it's OK.
  927.     cmp al,'a'
  928.     jb ver2
  929.     and al,137O        ; It's a-z, capitalize.
  930. ver1:    ret
  931.  
  932. ver2:    push es
  933.     mov cx,ds
  934.     mov es,cx        ; Scan uses ES register.
  935.     mov di,offset spchar2
  936.     mov cx,spc2len
  937. ver3:    repne scasb        ; Search string for input char.
  938.     pop es
  939.     je ver1            ; in table, return it
  940.     mov al,'X'        ; If illegal, replace with "X".
  941.     mov flags.nmoflg,1
  942.     ret
  943.  
  944. ; Print incoming filename(s). [21a]
  945. PRTFN    PROC    NEAR
  946.     call clrfln        ; Position cursor & blank out the line.
  947.     mov si,offset data    ; Where to put the name.
  948.     cmp flags.droflg,0    ; Drive specified?
  949.     je prtfn1
  950.     mov dl,fcb
  951.     add dl,'@'        ; Make it readable.
  952.     mov ah,dconio        ; Print the drive name. 
  953.     int dos
  954.     mov dl,':'
  955.     int dos
  956. prtfn1:    lodsb            ; get a byte from filename
  957.     cmp al,0        ; end of filename?
  958.     je prtfn2
  959.     mov dl,al
  960.     mov ah,conout
  961.     int dos            ; print the name
  962.     jmp prtfn1
  963. prtfn2:    ret
  964. PRTFN    ENDP
  965.  
  966. ; Print data onto the screen.  If text has no "$" in it, just print
  967. ; it.  Else, do special output for the "$".  
  968. ; Routine expects: DI = Start of buffer we are to print.
  969. ;           CX = Number of characters to print.     [21c]
  970.  
  971. PRTSCR    PROC    NEAR
  972.     mov al,'$'        ; This is what we're looking for.
  973.     mov oloc,di        ; Remember original buffer address. 
  974.     mov osiz,cx        ; And original size. 
  975.     push es
  976.     mov bx,ds
  977.     mov es,bx        ; Have ES point to data area.
  978. prts0:    repnz scasb        ; Search for "$" in the buffer.
  979.     cmp cx,0        ; Found one?
  980.     je prts1        ; No, do a regular DOS call.
  981.     mov ah,prstr
  982.     mov dx,oloc        ; Print up to the "$". 
  983.     int dos
  984.     mov ah,dconio
  985.     mov dl,'$'
  986.     int dos            ; Print the "$"
  987.     mov oloc,di        ; New starting location.
  988.     mov osiz,cx        ; New size.
  989.     jmp prts0
  990. prts1:    mov bx,oloc        ; The buffer location.
  991.     add bx,osiz        ; Point past the data.
  992.     mov [bx],al        ; Add "$" for printing.
  993.     mov ah,prstr
  994.     mov dx,oloc
  995.     int dos
  996.     pop es
  997.     ret
  998. PRTSCR    ENDP
  999.  
  1000. FIXFCB  PROC    NEAR    
  1001.     push ax            ; Don't forget this.  [22]
  1002.     mov bx,offset fcb+18
  1003.     mov di,offset filsiz
  1004.     mov ax,[bx]
  1005.     mov [di],ax
  1006.     mov bx,offset fcb+16
  1007.     mov ax,[bx]
  1008.     mov 2[di],ax
  1009.     pop ax            ; Get number of chars in last buffer full. [22]
  1010.     sub filsiz+2,ax        ; Get real file size.
  1011.     sbb filsiz,0
  1012.     mov bx,offset fcb+18
  1013.     mov di,offset filsiz
  1014.     mov ax,[di]
  1015.     mov [bx],ax
  1016.     mov bx,offset fcb+16
  1017.     mov ax,2[di]
  1018.     mov [bx],ax
  1019.     ret
  1020. FIXFCB    ENDP
  1021.  
  1022. ; find a unique filename...
  1023. ; enter with a ptr to a (null-terminated) filename in ax
  1024. ; returns a ptr to a new name in ax.  Ax will be null
  1025. ; if a unique name can't be made.
  1026. ; The idea is to change the last letter successively to a 0, 1, etc.
  1027. ; until a unique name is found...
  1028.  
  1029. unique    proc    near
  1030.     saveac    <bx,cx,dx,si,di>
  1031.     cld
  1032.     mov    si,ax            ; point to name
  1033.     mov    di,offset fnbuf        ; this is destination
  1034.     mov    cl,0            ; current length
  1035.     mov    dotpos,0        ; no dot found yet...
  1036.     mov    unum,-1            ; current "generation"
  1037. uniq1:    lodsb                ; get a byte
  1038.     stosb                ; and copy it
  1039.     cmp    al,'.'            ; have a dot?
  1040.     je    uniq2            ; no, keep looking
  1041.     cmp    al,0            ; maybe null at end?
  1042.     jne    uniq3            ; no, continue loop
  1043.     cmp    dotpos,0        ; seen dot yet?
  1044.     jne    uniq4            ; yes, exit loop
  1045. uniq2:    mov    dx,di            ; position of dot
  1046.     sub    dx,2            ; last non-dot
  1047.     mov    dotpos,dx        ; save position
  1048.     mov    dl,cl            ; # of chars before dot
  1049.     dec    dl            ; can't affect last one...
  1050.     mov    fnlen,dl        ; save length of string
  1051.     cmp    al,0            ; null at end?
  1052.     je    uniq4            ; yes, exit loop
  1053. uniq3:    inc    cl            ; bump character count
  1054.     jmp    uniq1            ; and continue loop
  1055.  
  1056. uniq4:    mov    ax,offset fnbuf        ; point to name
  1057.     call    isfile            ; does it exist?
  1058.     jc    uniq6            ; no, succeed now
  1059.     inc    unum            ; move to next generation
  1060.  
  1061.     mov    cl,fnlen        ; max # of digits to play with
  1062.     mov    bx,10            ; radix
  1063.     mov    dx,0
  1064.     mov    ax,unum            ; generation #
  1065.     mov    di,dotpos        ; position for characters
  1066.  
  1067. uniq5:    div    bx            ; compute digit
  1068.     add    dl,'0'            ; make printable
  1069.     mov    byte ptr [di],dl    ; put into right place
  1070.     cmp    ax,0            ; no more to do?
  1071.     jz    uniq4            ; no, try this name
  1072.     dec    cl            ; decrement # of allowable digits
  1073.     jz    uniq7            ; no more room, fail here...
  1074.     dec    di            ; decrement char pos
  1075.     mov    dx,0            ; high order part stays 0
  1076.     jmp    uniq5            ; and keep making number
  1077.  
  1078. uniq6:    mov    ax,offset fnbuf        ; point to name
  1079.     ret
  1080.  
  1081. uniq7:    mov    ax,0            ; fail
  1082.     ret
  1083.  
  1084. unique    endp
  1085.  
  1086. ; Jumping to this location is like retskp.  It assumes the instruction
  1087. ;   after the call is a jmp addr.
  1088.  
  1089. RSKP    PROC    NEAR
  1090.     pop bp
  1091.     add bp,3
  1092.     push bp
  1093.     ret
  1094. RSKP    ENDP
  1095.  
  1096. ; Jumping here is the same as a ret.
  1097.  
  1098. R    PROC    NEAR
  1099.     ret
  1100. R    ENDP
  1101.  
  1102. code    ends
  1103.     end
  1104.